#include "hal_init.h"
#include <dma.h>
#include <gpio.h>
#include <i2c.h>
#include <spi.h>
#include <usart.h>
#include "sys_log.h"
#include "hal_errorcode.h"
#include "common.h"
#include "hal_tlv.h"
#include <cfg_param.h>
#include <stdint.h>

#if MODEL_CHOICE == MODEL_MOTOR
#include <tim.h>
#else

#endif

extern uint16_t g_DeviceID;

struct PacketQueue g_MyQueue = {0};

void hal_init()
{

#ifdef BIN_MODE_OPEN
    // 修改向量中断表，APP_ADDRESS为APP区的FLASH起始地址
    SCB->VTOR = FLASH_APPLICATION_START_ADDRESS;
#endif

    // 系统HAL库初始化
    HAL_Init();

    // 系统时钟配置
    SystemClock_Config();

    // 外设初始化
    MX_GPIO_Init();
    MX_DMA_Init();

#if MODEL_CHOICE == MODEL_MOTOR
    MX_I2C3_Init();
    MX_SPI1_Init();
    MX_SPI2_Init();
    MX_SPI3_Init();
    MX_SPI4_Init();
    MX_TIM6_Init();
#else
    MX_I2C1_Init();
    systick_delay_ms(50); // TA激光器两块板上电有延时，因此这里缓冲50ms
    MX_I2C2_Init();
    MX_I2C3_Init();
    MX_SPI1_Init();
    MX_SPI2_Init();
    MX_SPI3_Init();
    MX_SPI4_Init();
    MX_SPI5_Init();
#endif
    MX_USART2_UART_Init();

#ifdef UASRT1_IS_ENABLE
    MX_USART1_UART_Init();
#endif
}

void hal_globeconfig_Init()
{
    // 队列参数初始化
    g_MyQueue.front     = 0;
    g_MyQueue.rear      = -1;
    g_MyQueue.itemcount = 0;

    // 错误码清零
    hal_ErrorcodeReset();
}

uint8_t hal_deviceid_Init()
{
    // 读取flash中的值
    uint32_t addr = FLASH_APPLICATION_PARAMETER_ADDRESS + FLASH_DEVICE_ID_FORMAT;

    uint8_t device_num[FLASH_DEVICE_ID_SIZE];

    memcpy(device_num, (uint8_t *)addr, FLASH_DEVICE_ID_SIZE);

    // 检验读取出来的id号是否符合格式
    if (device_num[0] == 0x55 && device_num[1] == 0xAA && device_num[4] == 0xCC)
    {
        // 将id号相加
        uint16_t check_sum = CheckSumCalc(&device_num[2], 2);
        // 如果校验通过则使用该id好，未通过则使用默认id
        uint16_t check_bit = Int8ToInt16BigEnd(&device_num[5]);

        if (check_sum == check_bit)
        {
            g_DeviceID = Int8ToInt16BigEnd(&device_num[2]);
            SLOG_I("lasermotor hal_deviceid_Init get g_DeviceID: %#x \t\r\n", g_DeviceID);
        }
        else
        {
            hal_ErrorCodeWrite(ERRORCODE_TYPE_COM_SYSTEM, s_Id_Abnormal_Flag, 0, ABNORMAL_STATE);
            return 1;
        }
    }
    else
    {
        hal_ErrorCodeWrite(ERRORCODE_TYPE_COM_SYSTEM, s_Id_Abnormal_Flag, 0, ABNORMAL_STATE);
        return 1;
    }

    return 0;
}

void SystemClock_Config()
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /** Configure the main internal regulator output voltage
     */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState       = RCC_HSE_BYPASS;
    RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource  = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM       = 6;
    RCC_OscInitStruct.PLL.PLLN       = 100;
    RCC_OscInitStruct.PLL.PLLP       = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ       = 2;
    RCC_OscInitStruct.PLL.PLLR       = 2;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /** Initializes the CPU, AHB and APB buses clocks
     */
    RCC_ClkInitStruct.ClockType      = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
    {
        Error_Handler();
    }
}